/*! \file container.h	
	This is the header file for container.cpp
	
	This contains the Container class
*/

#ifndef CONTAINER_H
#define CONTAINER_H

#include <iostream>
#include <list>

#include "guiconstants.h"
#include "component.h"
#include "listener.h"
#include "button.h"
using namespace std;

/**
	\class Container

	This represents a GUI component that can hold other components.

*/
class Container : public Component {
protected:
	/**
	* This list stores all of the components with this container as their parent
	*
	* The order in which components are added to this list determines the tab traversal
	* order.
	*/
	list<Component*> children;

	/**
	* The child with the focus.
	*/
	Component* focus;

	/**
	* The button that gets pressed when you press enter.
	*/

	Button* okayButton;

	/**
	* The button that gets pressed when you press escape.
	*/
	Button* cancelButton;
	
	
	int dragX, dragY;
	bool dragging;
	bool draggable;
	int resize; // this keeps track of what side you're dragging
	bool resizable;
	int minWidth; // these default to the defines in guiconstants... can't be resized to be less than this
	int minHeight; // these default to the defines in guiconstants
	
	/**
	* This is used by the key input function to tab forward or backward through
	* the children components.
	*/
	void tabTraverse();
public:
	/**
	* \param parent	the parent component
	* \param border whether this container should show a border around it.
	* \param sideID If there is a border, this will specify which image index to use for a side
	* \param cornerID If there is a border, this will specify which image index to use for a corner
	*/
	Container( Component* parent, bool border = false );

	virtual void childChangedSize( Component* which );

	/**
	* Allows this component to be dragged
	*/
	void setDraggable( bool draggable = true ) {
		this->draggable = draggable;
	}
	
	/**
	* Allows this component to be resized
	*/
	void setResizable( bool resizable = true ) {
		this->resizable = resizable;
	}
	
	/**
	* This sets the button that is pressed when the user presses enter.
	*/
	void setOkayButton( Button* b ) {
		okayButton = b;
	}
	
	/**
	* This sets the button that is pressed when the user presses escape.
	*/
	void setCancelButton( Button* b ) {
		cancelButton = b;
	}
	
	/**
	* This gives this child component the focus.
	*/
	void setFocus( Component* c ) {
		focus = c;
	}
	
	/**
	* This returns which child component has the focus.
	*/
	Component* getFocus() {
		return focus;
	}
	
	// containers can't scroll, this is used for scrollpanel, but it's here to prevent typecasting in textarea
	virtual int getScrollPosition() {
		return 0;
	}
	
	/**
	* Adds a new child to this container
	*/
	void add( Component* c );
	
	/**
	* This will propagate the update command to children
	*/
	virtual void update();
		
	/**
	* This draws the container if it is visible.
	* First, it draws the background of this component (probably just a gradient rect)
	* Second, it draws the children components on top of it by calling their draw() functions.
	* Finally, it draws a border around this component
	*/
	virtual void draw();
		
	/**
	* This is called when the size of the container changes. It sets the position and size
	* of its children, but this currently has to be done manually (as opposed to with sizers)
	*/
	virtual void layout();
	
	/**
	* This is overridden from the Component setSize so that it can call layout().
	* It actually calls Component::setSize() and then layout()
	*/
	virtual void setSize( int newW, int newH );
	
	/**
	* This is probably unused.
	*/
	virtual int getType() { return TYPE_CONTAINER; }
	
	/**
	* This runs Component::sendMouseUpEvent so that all of this Container's listeners are alerted, then
	* it also tells all of its children that a mouseUp event occurred.
	* This is in place because of the lock system. The "lock" is held by a top-level container, but
	* we would need to know which component was moused over or clicked, and that's not currently kept track of.
	* So instead of isolating the mouseUp event to that single component, we send it to everything, since it can't
	* do any harm.
	*/
	virtual void sendMouseUpEvent();
	
	/**
	* See \link sendMouseUpEvent \endlink
	*/
	virtual void sendOnLeaveEvent();
	
	virtual bool handleMouseMove( int mX, int mY );
	virtual bool handleMouseWheel( int pos );
	virtual bool handleMouseClick( int button, int state );
	virtual void handleKeyInput( int key, int state );
};

#endif
